package com.jagochan.imchat.module.user.service.impl;

import com.jagochan.imchat.module.common.interceptor.ContextInfoHolder;
import com.jagochan.imchat.module.common.utils.ThrowExceptionAsserts;
import com.jagochan.imchat.module.user.adaptor.UserAdaptor;
import com.jagochan.imchat.module.user.dao.UserDao;
import com.jagochan.imchat.module.user.domain.entity.ItemConfig;
import com.jagochan.imchat.module.user.domain.entity.User;
import com.jagochan.imchat.module.user.domain.entity.UserBackpack;
import com.jagochan.imchat.module.user.domain.enums.ItemEnum;
import com.jagochan.imchat.module.user.domain.enums.ItemTypeEnum;
import com.jagochan.imchat.module.user.domain.resp.BadgeResp;
import com.jagochan.imchat.module.user.domain.resp.UserInfoResp;
import com.jagochan.imchat.module.user.event.UserRegisterEvent;
import com.jagochan.imchat.module.user.service.ItemConfigService;
import com.jagochan.imchat.module.user.service.UserBackpackService;
import com.jagochan.imchat.module.user.service.UserService;
import com.jagochan.imchat.module.user.service.cache.ItemConfigCache;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    @Resource
    private UserBackpackService userBackpackService;

    @Resource
    private ItemConfigCache itemConfigCache;

    @Resource
    private ItemConfigService itemConfigService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long register(User user) {
        boolean success = userDao.save(user);
        // 发送自定义事件（用户注册事件）
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this, user));
        return user.getId();
    }

    @Override
    public UserInfoResp getUserInfo(Long uid) {
        User user = userDao.getById(uid);
        // 查询当前用户的某个物品（如 徽章，改名卡）数量
        Integer modifyNameCount = userBackpackService.countByItemId(uid, ItemEnum.MODIFY_NAME_CARD.getTypeEnum().getType());
        return UserAdaptor.buildUserInfoResp(user, modifyNameCount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyName(Long uid, String name) {
        // 【检查名称是否重复】
        User user = userDao.getByName(name);
        ThrowExceptionAsserts.isNotNull(user, "用户名已存在");
        // 【检查是否有改名卡】
        UserBackpack modifyNameCard = userBackpackService.getModifyNameCard(uid);
        ThrowExceptionAsserts.isNull(modifyNameCard, "您没有改名卡哦");

        // 使用改名卡
        Boolean success = userBackpackService.useModifyNameCard(modifyNameCard.getId());
        if (success) {
            userDao.updateName(ContextInfoHolder.get().getUid(), name);
        }
    }

    @Override
    public List<BadgeResp> badges(Long uid) {
        // 查询所有的徽章列表
        List<ItemConfig> badgeList = itemConfigCache.listBadge();

        // 查询当前用户拥有的徽章
        List<Long> badgeIdList = badgeList.stream().map(ItemConfig::getId).collect(Collectors.toList());
        List<UserBackpack> backpackList = userBackpackService.listByUidAndItemIds(uid, badgeIdList);

        // 查询用户当前佩戴的徽章
        User user = userDao.getById(uid);

        return UserAdaptor.buildBadgeRespList(badgeList, backpackList, user);
    }

    @Override
    public boolean wearBadge(Long uid, Long itemId) {
        // 确保当前用户拥有了该徽章
        UserBackpack userBackpack = userBackpackService.getValidByUidAndItemId(uid, itemId);
        ThrowExceptionAsserts.isNull(userBackpack, "您没有该徽章哦");
        // 确保该物品是徽章
        ItemConfig itemConfig = itemConfigService.getById(itemId);
        ThrowExceptionAsserts.isNull(itemConfig, "此徽章下架了哦");
        ThrowExceptionAsserts.notEqual(itemConfig.getType(), ItemTypeEnum.BADGE.getType(), "请勿使用非徽章物品哦");

        return userDao.updateById(User.builder().id(uid).itemId(itemId).build());
    }
}
